package pl.shenlon.ga.evaluation;

import java.util.Collections;
import java.util.List;

import pl.shenlon.ga.GeneticPokerPlayer;
import pl.shenlon.ga.Population;
import pl.shenlon.ga.Specimen;
import pl.shenlon.poker.game.PokerPlayer;
import pl.shenlon.poker.game.TestHand;
import pl.shenlon.poker.game.gametypes.NoLimitPokerGame;
import pl.shenlon.poker.game.gametypes.PokerGame;

import com.google.common.collect.Lists;

public class LinearPopulationEvaluator extends PopulationEvaluator {

	private int initialCash;

	private final GeneticPokerPlayer[] players;

	public LinearPopulationEvaluator(int size, int cash) {
		players = new GeneticPokerPlayer[size];
		for (int i = 0; i < size; i++) {
			players[i] = new GeneticPokerPlayer(cash);
		}
		initialCash = cash;
	}

	public LinearPopulationEvaluator(Population<?> population) {
		this(population.getPopulationSize(), population.getCash());
		setPopulation(population);
	}

	@Override
	public PokerPlayer evaluatePopulation(TestHand hand) {
		List<Integer> playersInGame = Lists
				.newArrayListWithCapacity(players.length);
		for (int i = 0; i < players.length; i++) {
			playersInGame.add(i);
		}
		Collections.shuffle(playersInGame);

		PokerGame game = new NoLimitPokerGame();
		game.getTableCards().setCards(hand.getTableCards().getCards());
		int playerAScore = 0, playerBScore = 0;

		GeneticPokerPlayer bestPlayer = players[0];
		for (int i = 0; i + 2 < players.length; i += 2) {
			GeneticPokerPlayer playerA = players[playersInGame.get(i)], playerB = players[playersInGame
					.get(i + 1)];
			playerA.getHand().setCards(hand.getPlayerACards().getCards());
			playerB.getHand().setCards(hand.getPlayerBCards().getCards());
			game.setPlayerA(playerA);
			game.setPlayerB(playerB);
			game.playGame(false);
			playerAScore = playerA.getCash() - initialCash;
			playerBScore = playerB.getCash() - initialCash;

			minScore = playerAScore < minScore ? playerAScore : minScore;
			minScore = playerBScore < minScore ? playerBScore : minScore;

			playerA.setCash(initialCash);
			playerB.setCash(initialCash);

			playerA.getSpecimen().updateScore(playerAScore);
			playerB.getSpecimen().updateScore(playerBScore);

			if (playerAScore > bestPlayer.getSpecimen().getScore()) {
				bestPlayer = playerA;
			}
			if (playerBScore > bestPlayer.getSpecimen().getScore()) {
				bestPlayer = playerB;

			}
		}
		if (minScore < 0) {
			minScore = Math.abs(minScore);
			for (GeneticPokerPlayer player : players) {
				player.getSpecimen().updateScore(minScore);
			}
		}
		return bestPlayer;
	}

	@Override
	public void setPopulation(Population<?> population) {
		initialCash = population.getCash();
		Specimen[] specimens = population.getPopulation();
		for (int i = 0; i < specimens.length; i++) {
			players[i].setSpecimen(specimens[i]);
			players[i].setCash(initialCash);
		}
	}

}
